package cn.chiship.framework.upms.biz.base.controller;

import cn.chiship.framework.common.constants.CommonCacheConstants;
import cn.chiship.framework.common.constants.CommonConstants;
import cn.chiship.framework.common.enums.LoginTypeEnum;
import cn.chiship.framework.upms.biz.base.service.CaptchaService;
import cn.chiship.framework.upms.biz.system.service.UpmsSmsCodeService;
import cn.chiship.framework.upms.biz.user.pojo.dto.UpmsUserPersonalInformationModifyDto;
import cn.chiship.framework.upms.biz.user.service.UpmsUserService;
import cn.chiship.sdk.cache.service.RedisService;
import cn.chiship.sdk.cache.service.UserCacheService;
import cn.chiship.sdk.cache.vo.CacheUserVO;
import cn.chiship.sdk.core.annotation.Authorization;
import cn.chiship.sdk.core.annotation.NoParamsSign;
import cn.chiship.sdk.core.annotation.NoVerificationAppIdAndKey;
import cn.chiship.sdk.core.annotation.NoVerificationProjectId;
import cn.chiship.sdk.core.base.constants.BaseConstants;
import cn.chiship.sdk.core.encryption.rsa.RsaEncrypt;
import cn.chiship.sdk.core.useragent.UserAgentUtil;
import cn.chiship.sdk.core.util.*;
import cn.chiship.sdk.core.util.ip.IpUtils;
import cn.chiship.sdk.framework.pojo.dto.*;
import cn.chiship.framework.common.annotation.LoginUser;
import cn.chiship.framework.common.annotation.SystemOptionAnnotation;
import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.framework.common.enums.BusinessTypeEnum;
import cn.chiship.framework.common.service.GlobalCacheService;
import cn.chiship.framework.upms.biz.user.service.UpmsUserLoginHistoryService;
import cn.chiship.framework.upms.biz.user.service.UpmsUserOnlineService;
import cn.chiship.sdk.framework.util.ServletUtil;
import cn.chiship.sdk.third.core.common.ThirdOauthLoginDto;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * 登录相关
 *
 * @author lijian
 */
@RestController
@RequestMapping("/sso")
@Api(tags = "登录控制器")
public class SsoController {

    private static final Logger LOGGER = LoggerFactory.getLogger(SsoController.class);

    private static final String STRING_MOBILE = "Mobile";

    private static final String STRING_SCAN = "scan";

    private static final String STRING_IS_C_L = "isConfirmLogin";

    /**
     * 验证码超期时间，单位：秒
     */
    private static final Long QR_CODE_EXPIRE = 60L;

    @Resource
    UserCacheService userCacheService;

    @Resource
    RedisService redisService;

    @Resource
    private UpmsUserService upmsUserService;

    @Resource
    private UpmsUserLoginHistoryService upmsUserLoginHistoryService;

    @Resource
    private GlobalCacheService globalCacheService;

    @Resource
    private UpmsSmsCodeService upmsSmsCodeService;

    @Resource
    private UpmsUserOnlineService upmsUserOnlineService;

    @Resource
    private CaptchaService captchaService;

    @SystemOptionAnnotation(describe = "用户名+密码登录", option = BusinessTypeEnum.SYSTEM_OPTION_LOGIN)
    @ApiOperation(value = "用户名+密码登录")
    @PostMapping("basicLogin")
    public ResponseEntity<BaseResult> basicLogin(HttpServletRequest request,
                                                 @RequestBody @Valid UserBaseLoginDto baseLoginDto) {
        String username = globalCacheService.rsaDecrypt(baseLoginDto.getUsername(), "用户名");
        String password = globalCacheService.rsaDecrypt(baseLoginDto.getPassword(), "密码");

        String ip = IpUtils.getIpAddr(request);
        LoginTypeEnum loginTypeEnum = LoginTypeEnum.LOGIN_PC;
        UserAgentUtil userAgent = UserAgentUtil.parseUserAgentString(ServletUtil.getRequest().getHeader("User-Agent"));
        String deviceType = userAgent.getOperatingSystem().getDeviceType().getName();
        if (STRING_MOBILE.equals(deviceType)) {
            loginTypeEnum = LoginTypeEnum.LOGIN_APP;
        }
        return new ResponseEntity<>(
                upmsUserService.login(request.getSession().getId(), username, password, ip, loginTypeEnum),
                HttpStatus.OK);
    }

    @SystemOptionAnnotation(describe = "用户名+密码+图形验证码登录", option = BusinessTypeEnum.SYSTEM_OPTION_LOGIN)
    @ApiOperation(value = "用户名+密码+图形验证码登录")
    @PostMapping("login")
    public ResponseEntity<BaseResult> login(HttpServletRequest request,
                                            @RequestBody @Valid UserCaptchaLoginDto userCaptchaLoginDto) {

        String username = globalCacheService.rsaDecrypt(userCaptchaLoginDto.getUsername(), "用户名");
        String password = globalCacheService.rsaDecrypt(userCaptchaLoginDto.getPassword(), "密码");

        String ip = IpUtils.getIpAddr(request);
        BaseResult baseResult = captchaService.verification(userCaptchaLoginDto.getVerificationCode());
        if (!baseResult.isSuccess()) {
            upmsUserLoginHistoryService.loginHistory(null, username, null, "验证码错误", BaseConstants.NO, ip,
                    LoginTypeEnum.LOGIN_PC);
            return new ResponseEntity<>(baseResult, HttpStatus.OK);
        }
        baseResult = globalCacheService.validateLoginIp(ip);
        if (!baseResult.isSuccess()) {
            return new ResponseEntity<>(baseResult, HttpStatus.OK);
        }
        return new ResponseEntity<>(
                upmsUserService.login(request.getSession().getId(), username, password, ip, LoginTypeEnum.LOGIN_PC),
                HttpStatus.OK);
    }

    @SystemOptionAnnotation(describe = "手机号登录", option = BusinessTypeEnum.SYSTEM_OPTION_LOGIN)
    @ApiOperation(value = "手机号登录")
    @PostMapping("mobileLogin")
    public ResponseEntity<BaseResult> mobileLogin(HttpServletRequest request,
                                                  @RequestBody @Valid UserMobileLoginDto mobileLoginDto) {

        String mobile = globalCacheService.rsaDecrypt(mobileLoginDto.getMobile(), "手机号");
        String ip = IpUtils.getIpAddr(request);
        BaseResult baseResult = globalCacheService.validateLoginIp(ip);
        if (!baseResult.isSuccess()) {
            return new ResponseEntity<>(baseResult, HttpStatus.OK);
        }
        baseResult = upmsSmsCodeService.verification(mobile, mobileLoginDto.getMobileVerificationCode());
        if (!baseResult.isSuccess()) {
            upmsUserLoginHistoryService.loginHistory(null, mobile, null, "手机验证码错误", BaseConstants.NO, ip,
                    LoginTypeEnum.LOGIN_PC);
            return new ResponseEntity<>(baseResult, HttpStatus.OK);
        }

        return new ResponseEntity<>(
                upmsUserService.mobileLogin(request.getSession().getId(), mobile, ip, LoginTypeEnum.LOGIN_PC),
                HttpStatus.OK);
    }

    @SystemOptionAnnotation(describe = "钉钉授权码登录", option = BusinessTypeEnum.SYSTEM_OPTION_LOGIN)
    @ApiOperation(value = "钉钉授权码登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authCode", required = true, value = "授权码", dataTypeClass = String.class, paramType = "body"),
    })
    @PostMapping("dingTalk/authCodeLogin")
    public ResponseEntity<BaseResult> dingTalkAuthCodeLogin(HttpServletRequest request, @RequestBody @Valid String authCode) {
        if (StringUtil.isNullOrEmpty(authCode)) {
            return new ResponseEntity<>(BaseResult.error("授权码不能为空"), HttpStatus.OK);
        }
        String ip = IpUtils.getIpAddr(request);
        BaseResult baseResult = globalCacheService.validateLoginIp(ip);
        if (!baseResult.isSuccess()) {
            return new ResponseEntity<>(baseResult, HttpStatus.OK);
        }
        return new ResponseEntity<>(
                upmsUserService.dingTalkAuthCodeLogin(request.getSession().getId(), authCode, ip, LoginTypeEnum.LOGIN_DING_TALK),
                HttpStatus.OK);
    }

    @SystemOptionAnnotation(describe = "三方二维码授权链接", option = BusinessTypeEnum.SYSTEM_OPTION_LOGIN)
    @ApiOperation(value = "三方二维码授权链接")
    @ApiImplicitParams({
    })
    @PostMapping("third/oauth2Auth")
    public ResponseEntity<BaseResult> thirdOauth2Auth(@RequestBody @Valid ThirdOauthLoginDto thirdOauthLoginDto) {
        return new ResponseEntity<>(upmsUserService.thirdOauth2Auth(thirdOauthLoginDto), HttpStatus.OK);
    }

    @ApiOperation(value = "钉钉二维码授权跳转链接")
    @GetMapping(value = "dingTalk/redirectUri/{appId}")
    @NoParamsSign
    @NoVerificationAppIdAndKey
    @NoVerificationProjectId
    public ModelAndView dingTalkRedirectUri(HttpServletRequest request, @PathVariable("appId") String appId) throws Exception {
        //后期根据appId 去redis获取其他配置信息来实例化钉钉服务
        String code = request.getParameter("authCode");
        String ip = IpUtils.getIpAddr(request);
        BaseResult baseResult = upmsUserService.dingTalkOauth2AuthLogin(request.getSession().getId(), code, ip, LoginTypeEnum.LOGIN_DING_TALK);
        LOGGER.info("dingTalkSnsCodeLogin:{}", JSON.toJSONString(baseResult));
        Map<String, Object> query = new HashMap<>(8);
        query.put("success", baseResult.isSuccess());
        if (baseResult.isSuccess()) {
            query.put("accessToken", baseResult.getData());
        } else {
            query.put("errorMsg", URLEncoder.encode(baseResult.getData().toString(), "UTF-8"));
        }
        String url = new String(Base64Util.decode(request.getParameter("state")));
        PrintUtil.console(UrlUtil.analyticUrlMap(url));
        String callbackUrl = UrlUtil.buildUrl(url, query);
        callbackUrl = URLDecoder.decode(callbackUrl, BaseConstants.UTF8);
        LOGGER.info("callback:{}", callbackUrl);
        return new ModelAndView(new RedirectView(callbackUrl));
    }

    @ApiOperation(value = "企业微信二维码授权跳转链接")
    @GetMapping(value = "wxWork/redirectUri/{appId}")
    @NoParamsSign
    @NoVerificationAppIdAndKey
    @NoVerificationProjectId
    public ModelAndView wxWorkRedirectUri(HttpServletRequest request, @PathVariable("appId") String appId) throws Exception {
        String ip = IpUtils.getIpAddr(request);
        //后期根据appId 去redis获取其他配置信息来实例化企业微信服务
        String code = request.getParameter("code");
        LOGGER.info("企业微信二维码授权跳转链接执行了，{}", code);
        BaseResult baseResult = upmsUserService.wxWorkOauth2AuthLogin(request.getSession().getId(), code, ip, LoginTypeEnum.LOGIN_WX_WORK);
        String url = new String(Base64Util.decode(request.getParameter("state")));
        Map<String, Object> query = new HashMap<>(8);
        query.put("success", baseResult.isSuccess());
        if (baseResult.isSuccess()) {
            query.put("accessToken", baseResult.getData());
        } else {
            query.put("errorMsg", URLEncoder.encode(baseResult.getData().toString(), "UTF-8"));
        }
        String callbackUrl = UrlUtil.buildUrl(url, query);
        callbackUrl = URLDecoder.decode(callbackUrl, BaseConstants.UTF8);
        LOGGER.info("callback:{}", callbackUrl);
        return new ModelAndView(new RedirectView(callbackUrl));
    }


    @SystemOptionAnnotation(describe = "获得二维码登录字符串", option = BusinessTypeEnum.SYSTEM_OPTION_LOGIN)
    @ApiOperation(value = "获得二维码登录字符串")
    @PostMapping("/getQRImage")
    public ResponseEntity<BaseResult> getQrImage() {

        // 生成唯一ID
        String uuid = RandomUtil.number(6) + RandomUtil.uuidLowerCase();
        String content = uuid + ";" + (System.currentTimeMillis() + QR_CODE_EXPIRE * 1000) + ";"
                + CommonConstants.COMMON_PROJECT_NAME;

        byte[] cipherData = RsaEncrypt.encrypt(RsaEncrypt.loadPublicKeyByStr(globalCacheService.getRsaPublicKey()),
                content.getBytes());
        String cipher = Base64Util.encode(cipherData);
        JSONObject json = new JSONObject();
        json.put("imageId", uuid);
        json.put("qrCode", cipher);
        redisService.hset(CommonCacheConstants.buildKey(CommonCacheConstants.REDIS_QRCODE_LOGIN_PREFIX), uuid, json,
                QR_CODE_EXPIRE);

        json = new JSONObject();
        json.put("imageId", uuid);
        json.put("qrCode", cipher);
        redisService.hset(CommonCacheConstants.buildKey(CommonCacheConstants.REDIS_QRCODE_LOGIN_PREFIX), cipher, json,
                QR_CODE_EXPIRE);
        return new ResponseEntity<>(BaseResult.ok(json), HttpStatus.OK);
    }

    @ApiOperation(value = "获取登录二维码状态")
    @ApiImplicitParams({@ApiImplicitParam(name = "imageId", value = "二维码唯一标识", dataTypeClass = String.class,
            paramType = "path", required = true),})
    @PostMapping("/getQRImageStatus/{imageId}")
    public ResponseEntity<BaseResult> getQrImageStatus(@PathVariable(value = "imageId") String imageId) {
        Map<String, Object> map = Maps.newHashMapWithExpectedSize(7);
        int code = -1;
        try {
            String key = CommonCacheConstants.buildKey(CommonCacheConstants.REDIS_QRCODE_LOGIN_PREFIX);
            if (!redisService.hHasKey(key, imageId)) {
                return new ResponseEntity<>(BaseResult.ok(-1), HttpStatus.OK);
            }
            JSONObject json = (JSONObject) redisService.hget(key, imageId);
            if (json.containsKey(STRING_SCAN)) {
                if (Boolean.TRUE.equals(json.getBoolean(STRING_SCAN))) {
                    // 手机端已扫码，通知pc个性化展示
                    code = 1;
                }
            } else if (json.containsKey(STRING_IS_C_L)) {
                if (Boolean.TRUE.equals(json.getBoolean(STRING_IS_C_L))) {
                    // 手机端确认登录，并且传递了用户名和密码
                    String token = json.getString("token");
                    code = 2;
                    map.put("token", token);
                }
            } else {
                // 未扫码，未登录
                code = 0;
            }
        } catch (Exception e) {
            LOGGER.error("获取登录二维码状态发生异常：{}", e.getLocalizedMessage());
        }
        map.put("code", code);
        return new ResponseEntity<>(BaseResult.ok(map), HttpStatus.OK);
    }

    @ApiOperation(value = "扫码登录")
    @PostMapping("/doQRCodeScan")
    public ResponseEntity<BaseResult> doQrCodeScan(HttpServletRequest request, @RequestBody @Valid String qrCode,
                                                   @ApiIgnore @LoginUser CacheUserVO userVO) {
        try {
            String key = CommonCacheConstants.buildKey(CommonCacheConstants.REDIS_QRCODE_LOGIN_PREFIX);
            JSONObject json = (JSONObject) redisService.hget(key, qrCode);
            if (StringUtil.isNull(json)) {
                return new ResponseEntity<>(BaseResult.error("请扫描正确的二维码"), HttpStatus.OK);
            }
            String imageId = json.getString("imageId");
            json.put("scan", true);
            redisService.hset(key, imageId, json, QR_CODE_EXPIRE);
            String ip = IpUtils.getIpAddr(request);
            BaseResult baseResult = globalCacheService.validateLoginIp(ip);
            if (!baseResult.isSuccess()) {
                return new ResponseEntity<>(baseResult, HttpStatus.OK);
            }
            Thread.sleep(1000);
            baseResult = upmsUserService.scanLogin(request.getSession().getId(), userVO.getUsername(), ip,
                    LoginTypeEnum.LOGIN_SCAN);
            if (!baseResult.isSuccess()) {
                return new ResponseEntity<>(baseResult, HttpStatus.OK);
            }
            json = (JSONObject) redisService.hget(key, qrCode);
            json.put(STRING_IS_C_L, true);
            json.put("token", baseResult.getData());
            redisService.hset(key, imageId, json, QR_CODE_EXPIRE);
            return new ResponseEntity<>(BaseResult.ok(), HttpStatus.OK);

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return new ResponseEntity<>(BaseResult.error("二维码已失效,请重新生成!"), HttpStatus.OK);
        }
    }

    @SystemOptionAnnotation(describe = "用户注册", option = BusinessTypeEnum.SYSTEM_OPTION_UPDATE)
    @ApiOperation(value = "用户注册")
    @PostMapping(value = "register")
    public ResponseEntity<BaseResult> register(@RequestBody @Valid UserRegisterDto userRegisterDto) {
        BaseResult baseResult = upmsSmsCodeService.verification(userRegisterDto.getMobile(),
                userRegisterDto.getVerificationCode());
        if (!baseResult.isSuccess()) {
            return new ResponseEntity<>(baseResult, HttpStatus.OK);
        }
        return new ResponseEntity<>(upmsUserService.register(userRegisterDto.getMobile(), userRegisterDto.getRealName(),
                userRegisterDto.getPassword(), userRegisterDto.getPasswordAgain()), HttpStatus.OK);
    }

    @SystemOptionAnnotation(describe = "检查用户是否加入组织")
    @ApiOperation(value = "检查用户是否加入组织")
    @ApiImplicitParams({@ApiImplicitParam(name = "invitationCode", value = "组织邀请码", dataTypeClass = String.class,
            paramType = "path", required = true),})
    @GetMapping(value = "checkJoinOrg/{invitationCode}")
    public ResponseEntity<BaseResult> checkJoinOrg(@PathVariable("invitationCode") String invitationCode,
                                                   @ApiIgnore @LoginUser CacheUserVO userVO) {
        return new ResponseEntity<>(upmsUserService.checkJoinOrg(StringUtil.getString(userVO.getId()), invitationCode),
                HttpStatus.OK);
    }

    @SystemOptionAnnotation(describe = "加入组织", option = BusinessTypeEnum.SYSTEM_OPTION_UPDATE)
    @ApiOperation(value = "加入组织")
    @PostMapping(value = "joinOrg")
    public ResponseEntity<BaseResult> joinOrg(@RequestBody @Valid UserJoinOrgDto userJoinOrgDto,
                                              @ApiIgnore @LoginUser CacheUserVO userVO) {
        return new ResponseEntity<>(
                upmsUserService.joinOrg(userVO, userJoinOrgDto.getInvitationCode(), userJoinOrgDto.getRealName()),
                HttpStatus.OK);
    }

    @SystemOptionAnnotation(describe = "离开组织", option = BusinessTypeEnum.SYSTEM_OPTION_REMOVE)
    @ApiImplicitParams({@ApiImplicitParam(name = "organizationId", value = "组织ID", required = true,
            dataTypeClass = String.class, paramType = "path")})
    @ApiOperation(value = "离开组织")
    @PostMapping(value = "leaveOrg/{organizationId}")
    public ResponseEntity<BaseResult> leaveOrg(@PathVariable("organizationId") String organizationId,
                                               @ApiIgnore @LoginUser CacheUserVO userVO) {
        return new ResponseEntity<>(upmsUserService.leaveOrg(userVO, organizationId), HttpStatus.OK);
    }

    @SystemOptionAnnotation(describe = "进入企业")
    @ApiImplicitParams({@ApiImplicitParam(name = "organizationId", value = "组织ID", required = true,
            dataTypeClass = String.class, paramType = "path")})
    @ApiOperation(value = "进入企业")
    @PostMapping(value = "enterOrg/{organizationId}")
    public ResponseEntity<BaseResult> enterOrg(@PathVariable("organizationId") String organizationId,
                                               @ApiIgnore @LoginUser CacheUserVO userVO) {
        return new ResponseEntity<>(upmsUserService.enterOrg(userVO, organizationId), HttpStatus.OK);
    }

    @SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_OTHER, describe = "解散企业")
    @ApiOperation(value = "解散企业")
    @PostMapping(value = "dissolution")
    public ResponseEntity<BaseResult> dissolution(@RequestBody @Valid String organizationId,
                                                  @ApiIgnore @LoginUser CacheUserVO userVO) {
        return new ResponseEntity<>(upmsUserService.dissolutionOrg(userVO, organizationId), HttpStatus.OK);

    }

    @SystemOptionAnnotation(describe = "切换部门")
    @ApiImplicitParams({@ApiImplicitParam(name = "deptId", value = "部门ID", required = true,
            dataTypeClass = String.class, paramType = "path")})
    @ApiOperation(value = "切换部门")
    @PostMapping(value = "changeDept/{deptId}")
    public ResponseEntity<BaseResult> changeDept(@PathVariable("deptId") String deptId,
                                                 @ApiIgnore @LoginUser CacheUserVO userVO) {
        return new ResponseEntity<>(upmsUserService.changeDept(userVO, deptId), HttpStatus.OK);
    }

    @SystemOptionAnnotation(describe = "修改密码", option = BusinessTypeEnum.SYSTEM_OPTION_UPDATE)
    @ApiOperation(value = "修改密码")
    @Authorization
    @PostMapping(value = "modifyPassword")
    public ResponseEntity<BaseResult> modifyPassword(@RequestBody @Valid UserModifyPasswordDto userModifyPasswordDto,
                                                     @ApiIgnore @LoginUser CacheUserVO userVO) {
        BaseResult baseResult = upmsSmsCodeService.verification(userVO.getMobile(), userModifyPasswordDto.getVerificationCode());
        if (!baseResult.isSuccess()) {
            return new ResponseEntity<>(baseResult, HttpStatus.OK);
        }
        return new ResponseEntity<>(upmsUserService.modifyPassword(userVO.getId(), userModifyPasswordDto), HttpStatus.OK);
    }

    @SystemOptionAnnotation(describe = "忘记密码", option = BusinessTypeEnum.SYSTEM_OPTION_UPDATE)
    @ApiOperation(value = "忘记密码")
    @PostMapping(value = "forgotPassword")
    public ResponseEntity<BaseResult> forgotPassword(@RequestBody @Valid UserForgotPasswordDto userForgotPasswordDto) {
        BaseResult baseResult = upmsSmsCodeService.verification(userForgotPasswordDto.getMobile(),
                userForgotPasswordDto.getVerificationCode());
        if (!baseResult.isSuccess()) {
            return new ResponseEntity<>(baseResult, HttpStatus.OK);
        }
        return new ResponseEntity<>(upmsUserService.forgotPassword(userForgotPasswordDto), HttpStatus.OK);
    }

    @SystemOptionAnnotation(describe = "修改个人信息", option = BusinessTypeEnum.SYSTEM_OPTION_UPDATE)
    @ApiOperation(value = "修改个人信息")
    @Authorization
    @PostMapping(value = "modifyPersonInfo")
    public ResponseEntity<BaseResult> modifyPersonInfo(
            @RequestBody @Valid UpmsUserPersonalInformationModifyDto personalInformationModifyDto,
            @ApiIgnore @LoginUser CacheUserVO userVO) {
        return new ResponseEntity<>(upmsUserService.modifyPersonInfo(userVO.getId(), personalInformationModifyDto),
                HttpStatus.OK);
    }



    @SystemOptionAnnotation(describe = "修改手机号", option = BusinessTypeEnum.SYSTEM_OPTION_UPDATE)
    @ApiOperation(value = "修改手机号")
    @Authorization
    @PostMapping(value = "modifyMobile")
    public ResponseEntity<BaseResult> modifyMobile(@RequestBody @Valid UserModifyMobileDto userModifyMobileDto,
                                                   @ApiIgnore @LoginUser CacheUserVO userVO) {
        BaseResult baseResult = upmsSmsCodeService.verification(userVO.getMobile(),
                userModifyMobileDto.getVerificationCode());
        if (!baseResult.isSuccess()) {
            return new ResponseEntity<>(BaseResult.error("【原手机验证码】：" + baseResult.getData()), HttpStatus.OK);
        }
        baseResult = upmsSmsCodeService.verification(userModifyMobileDto.getNewMobile(),
                userModifyMobileDto.getNewVerificationCode());
        if (!baseResult.isSuccess()) {
            return new ResponseEntity<>(BaseResult.error("【新手机验证码】：" + baseResult.getData()), HttpStatus.OK);
        }
        return new ResponseEntity<>(upmsUserService.modifyMobile(userModifyMobileDto.getNewMobile(), userVO),
                HttpStatus.OK);
    }

    @SystemOptionAnnotation(describe = "修改邮箱", option = BusinessTypeEnum.SYSTEM_OPTION_UPDATE)
    @ApiOperation(value = "修改邮箱")
    @Authorization
    @PostMapping(value = "modifyEmail")
    public ResponseEntity<BaseResult> modifyEmail(@RequestBody @Valid UserModifyEmailDto userModifyEmailDto,
                                                  @ApiIgnore @LoginUser CacheUserVO userVO) {
        BaseResult baseResult = upmsSmsCodeService.verification(userVO.getMobile(),
                userModifyEmailDto.getVerificationCode());
        if (!baseResult.isSuccess()) {
            return new ResponseEntity<>(BaseResult.error("【手机验证码】：" + baseResult.getData()), HttpStatus.OK);
        }
        baseResult = upmsSmsCodeService.verification(userModifyEmailDto.getNewEmail(),
                userModifyEmailDto.getEmailVerificationCode());
        if (!baseResult.isSuccess()) {
            return new ResponseEntity<>(BaseResult.error("【邮箱验证码】：" + baseResult.getData()), HttpStatus.OK);
        }
        return new ResponseEntity<>(upmsUserService.modifyEmail(userModifyEmailDto.getNewEmail(), userVO),
                HttpStatus.OK);
    }

    @SystemOptionAnnotation(describe = "修改头像")
    @ApiOperation(value = "修改头像")
    @PostMapping("/modifyAvatar")
    @Authorization
    public ResponseEntity<BaseResult> modifyAvatar(@RequestBody @Valid @NotEmpty String avatar,
                                                   @ApiIgnore @LoginUser CacheUserVO userVO) {
        return new ResponseEntity<>(upmsUserService.modifyAvatar(avatar, userVO), HttpStatus.OK);
    }

    @SystemOptionAnnotation(describe = "设置用户名")
    @ApiOperation(value = "设置用户名")
    @PostMapping(value = "modifyUserName")
    @Authorization
    public ResponseEntity<BaseResult> modifyUserName(@RequestBody @Valid @NotEmpty String userName,
                                                     @ApiIgnore @LoginUser CacheUserVO userVO) {
        return new ResponseEntity<>(upmsUserService.modifyUserName(userName, StringUtil.getString(userVO.getId())),
                HttpStatus.OK);
    }

    @ApiOperation(value = "获得用户信息")
    @GetMapping("/getInfo")
    @Authorization
    public ResponseEntity<BaseResult> getInfo(@ApiIgnore @LoginUser CacheUserVO userVO) {
        return new ResponseEntity<>(BaseResult.ok(userVO), HttpStatus.OK);
    }

    @ApiOperation(value = "获得当前登录用户信息")
    @GetMapping("/getCurrentUserInfo")
    @Authorization
    public ResponseEntity<BaseResult> getCurrentUserInfo(@ApiIgnore @LoginUser CacheUserVO userVO) {
        return new ResponseEntity<>(BaseResult.ok(upmsUserService.selectByPrimaryKey(userVO.getId())), HttpStatus.OK);
    }

    @ApiOperation(value = "获得当前登录用户权限")
    @GetMapping("/getPermission")
    @Authorization
    public ResponseEntity<BaseResult> getPermission(@ApiIgnore @LoginUser CacheUserVO userVO) {
        return new ResponseEntity<>(upmsUserService.getPermission(userVO.getId()), HttpStatus.OK);
    }


    @SystemOptionAnnotation(describe = "注销登录", option = BusinessTypeEnum.SYSTEM_OPTION_LOGOUT)
    @ApiOperation(value = "注销登录")
    @PostMapping("/logout")
    @Authorization
    public ResponseEntity<BaseResult> logout(@ApiIgnore @LoginUser CacheUserVO userVO) {
        userCacheService.removeUser();
        upmsUserOnlineService.forceLogout(userVO.getSessionId());
        return new ResponseEntity<>(BaseResult.ok(), HttpStatus.OK);
    }

    @SystemOptionAnnotation(describe = "解锁", option = BusinessTypeEnum.SYSTEM_OPTION_OTHER)
    @ApiOperation(value = "解锁")
    @PostMapping("/unlock")
    @Authorization
    public ResponseEntity<BaseResult> unlock(HttpServletRequest request, @RequestBody String password,
                                             @ApiIgnore @LoginUser CacheUserVO userVO) {
        password = globalCacheService.rsaDecrypt(password, "密码");
        String ip = IpUtils.getIpAddr(request);
        return new ResponseEntity<>(upmsUserService.unlock(userVO.getId(), password, ip), HttpStatus.OK);
    }

}
